package com.zdc.encrypt;

import cn.hutool.core.io.FileUtil;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author zdc
 * @description
 * @date 2025/8/14 10:29
 */
public class MultiYamlEncryptor {

    private static final String ALGORITHM = "PBEWithMD5AndDES";
    private static final String _PASSWORD_ = "1234abcdABCD";
    private final String password;
    private final String dir;

    public MultiYamlEncryptor(String password, String dir) {
        this.password = password;
        this.dir = dir;
    }

    // 加密并压缩单个YAML文件
    public byte[] encryptYaml(String yamlContent) throws IOException {
        StandardPBEStringEncryptor encryptor = createEncryptor();
        String encrypted = encryptor.encrypt(yamlContent);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(out)) {
            gzOut.write(encrypted.getBytes("UTF-8"));
        }
        return out.toByteArray();
    }

    // 解密并解压单个YAML文件
    public String decryptYaml(byte[] encryptedData) {
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try (ByteArrayInputStream in = new ByteArrayInputStream(encryptedData);
                 GzipCompressorInputStream gzIn = new GzipCompressorInputStream(in)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = gzIn.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            }
            StandardPBEStringEncryptor encryptor = createEncryptor();
            return encryptor.decrypt(out.toString("UTF-8"));
        } catch (Exception e) {
            throw new RuntimeException("解密密码错误！！！！！");
        }
    }

    // 加密resources目录下所有YAML文件
    public Map<String, byte[]> encryptAllYamls() throws Exception {
        Map<String, byte[]> encryptedFiles = new HashMap<>();
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("file:" + dir + "*.yml");

        for (Resource resource : resources) {
            if (resource.getFilename().endsWith(".yml.gz")) {
                continue; // 跳过已加密文件
            }
            String content = FileUtil.readString(resource.getFile(), "UTF-8");
            byte[] encrypted = encryptYaml(content);
            encryptedFiles.put(getEncryptedFilename(resource.getFilename()), encrypted);
        }

        return encryptedFiles;
    }

    // 解密所有已加密文件
    public Map<String, String> decryptAllYamls() throws Exception {
        Map<String, String> decryptedFiles = new HashMap<>();
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("file:" + dir + "*.yml.gz");
        for (Resource resource : resources) {
            if (!Objects.requireNonNull(resource.getFilename()).endsWith(".yml.gz")) {
                continue;
            }
            byte[] encrypted = Files.readAllBytes(resource.getFile().toPath());
            String decrypted = decryptYaml(encrypted);
            FileUtil.del(dir + resource.getFilename());
            decryptedFiles.put(resource.getFilename().replace(".yml.gz", ".yml"), decrypted);
        }
        return decryptedFiles;
    }

    private StandardPBEStringEncryptor createEncryptor() {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setAlgorithm(ALGORITHM);
        encryptor.setPassword(password);
        return encryptor;
    }

    private String getEncryptedFilename(String original) {
        return original.replace(".yml", ".yml.gz").replace(".yaml", ".yml.gz");
    }
}